import json
import logging
import time
import uuid

from base.connection import mongodb_util
from base.request import ApiBaseHandler
from common.definition import ret_msg
from conf.config import DOMAIN
from debug.mqtt_publish import send_mqtt_msg
from helper.device import get_device_list

logger = logging.getLogger("wechat.handlers.device_contorl")


class Setup(ApiBaseHandler):
    def get_msg(self, device_id, type, value=None, ssid=None, password=None):
        """
        传递的消息
        :param device_id:
        :param type:
        :param value:
        :param ssid:
        :param password:
        :return:
        """
        timestamp = int(time.time())
        msg_uri = str(timestamp) + "-cTPPdiiiSumT-msg_uri"
        msg_id = str(uuid.uuid1())
        msg = [{
            "msg_type": "control",
            "msg_id": msg_id,
            "msg_uri": msg_uri,
            "operation": "add",
            "life": {
                "expire": "",
                "type": "forever"
            },
            "msg_data": {},
            "receiver": device_id,
            "create_time": timestamp,
            "sender": "admin",
        }]
        data = msg[0]["msg_data"]
        if type == "wifi":
            data["type"] = type
            data["ssid"] = ssid
            data["password"] = password
        else:
            data["type"] = type
            data["value"] = value
        logger.info("msg: %s" % msg)
        return msg

    def send_msg(self, device_id, msg):
        """
        发送mqtt消息
        :param device_id:
        :param msg:
        :return:
        """
        try:
            send_mqtt_msg(device_id, msg)
        except Exception as e:
            logger.error("发送消息失败：%s" % e)
            return self.finish(ret_msg(code=-1, error_message="消息发送失败！"))
        return self.finish(ret_msg())

    def merge_send_msg(self, device_id, type, upper_limit=None, lower_limit=None):
        """
        统一发送消息
        :param device_id:
        :param type:
        :param upper_limit:
        :param lower_limit:
        :return:
        """
        if type in ["air-dry", "lighting"]:
            value = self.get_parameter("value", None)
            if not value or value not in ["on", "off"]:
                return self.finish(ret_msg(code=-1, error_message="请求参数错误！"))
        else:
            value = int(self.get_parameter("value", 0))
            if type == "volume":
                error_message = "音量设置超出调控范围！"
            else:
                error_message = "温度设置超出调控范围！"
            if value < lower_limit or value > upper_limit:
                return self.finish(ret_msg(code=-1, error_message=error_message))
        msg = self.get_msg(device_id, type, value)
        self.send_msg(device_id, msg)

    def setup_temperature(self, device_id):
        """
        设置温度
        :param device_id:
        :return:
        """
        type = "temperature"
        upper_limit = 20
        lower_limit = 11
        self.merge_send_msg(device_id, type, upper_limit, lower_limit)

    def setup_air_dry(self, device_id):
        """
        设置风干
        :param device_id:
        :return:
        """
        type = "air-dry"
        self.merge_send_msg(device_id, type)

    def setup_lighting(self, device_id):
        """
        设置灯光
        :param device_id:
        :return:
        """
        type = "lighting"
        self.merge_send_msg(device_id, type)

    def setup_volume(self, device_id):
        """
        设置音量
        :return:
        """
        type = "volume"
        upper_limit = 100
        lower_limit = 0
        self.merge_send_msg(device_id, type, upper_limit, lower_limit)

    def setup_wifi(self, device_id):
        """
        设置wifi
        :param device_id:
        :return:
        """
        type = "wifi"
        ssid = self.get_parameter("ssid", None)
        password = self.get_parameter("password", None)
        if not ssid:
            return self.finish(ret_msg(code=-1, error_message="请求参数错误！"))
        msg = self.get_msg(device_id, type, ssid=ssid, password=password)
        self.send_msg(device_id, msg)

    async def get(self):
        # open_id = await self.get_open_id()
        device_id = self.get_parameter("device", None)
        if not device_id:
            return self.finish(ret_msg(code=-1, error_message="请求参数错误！"))
        # device_list = get_device_list(open_id)
        # if device_id not in device_list:
        #     return self.finish(ret_msg(code=-1, error_message="用户没有绑定该设备！"))
        msg = [{"msg_type": "status"}]
        send_mqtt_msg(device_id, msg)
        id = "xingxing/user/" + device_id
        try:
            db = mongodb_util.db
            result = db.sdec_device_status.find_one({"_id": id})
            logger.info("device_status=%s" % result)
            if result:
                wifi = result.get("wifi", None)
                if not wifi:
                    result["wifi"] = {}
            else:
                send_mqtt_msg(device_id, msg)
                return self.write(ret_msg(code=-1, data={}, error_message="系统繁忙, 请重新请求！"))
        except Exception as e:
            logger.error(e)
        return self.finish(ret_msg(data=result))

    async def post(self):
        # open_id = await self.get_open_id()
        device_id = self.get_parameter("device_id", None)
        type = self.get_parameter("type", None)
        if not all((device_id, type)):
            return self.finish(ret_msg(code=-1, error_message="请求参数错误！"))
        # device_list = get_device_list(open_id)
        # if device_id not in device_list:
        #     return self.finish(ret_msg(code=-1, error_message="用户没有绑定该设备！"))
        # 1=temperature=温度, 2=air-dry=风干, 3=lighting=灯光, 4=volume=音量, 5=wifi=wifi
        type = int(type)
        type_list = [1, 2, 3, 4, 5]
        if type not in type_list:
            return self.finish(ret_msg(code=-1, error_message="目前只支持温度、风干、音量、灯光、wifi设置！"))
        switch = {
            1: self.setup_temperature,
            2: self.setup_air_dry,
            3: self.setup_lighting,
            4: self.setup_volume,
            5: self.setup_wifi
        }
        switch[type](device_id)


class DeviceList(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        device_list = get_device_list(open_id)
        return self.write(ret_msg(data=device_list))


class SaveDeviceStatus(ApiBaseHandler):
    async def get(self):
        try:
            db = mongodb_util.db
            result = db.sdec_device_status.find()
            devices = []
            if result:
                for device in result:
                    devices.append(device)
        except Exception as e:
            logger.error(e)
            return self.write(ret_msg(code=-1, error_message="查询设备状态出错，请稍后重试！"))

        return self.write(ret_msg(data=devices))

    async def post(self):
        device_id = self.get_parameter("device_id", None)
        temperature = self.get_parameter("temperature", None)
        air_dry = self.get_parameter("air_dry", None)
        lighting = self.get_parameter("lighting", None)
        volume = self.get_parameter("volume", None)
        wifi = self.get_parameter("wifi", None)
        id = "xingxing/user/" + device_id
        logger.info("result=%s" % self.json_args)

        if not all([device_id, air_dry, lighting]):
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        temperature = int(temperature)
        volume = int(volume)

        if volume > 100 or volume < 0:
            return self.write(ret_msg(code=-1, error_message="音量设置错误！"))

        if air_dry not in ["on", "off"]:
            return self.write(ret_msg(code=-1, error_message="风干设置错误！"))

        if lighting not in ["on", "off"]:
            return self.write(ret_msg(code=-1, error_message="灯光设置错误！"))

        try:
            db = mongodb_util.db
            result = db.sdec_device_status.find_one({"_id": id})
            data = dict(
                _id=id,
                temperature=temperature,
                air_dry=air_dry,
                lighting=lighting,
                volume=volume,
                wifi=wifi if wifi else {}
            )

            if result:
                db.sdec_device_status.update({"_id": id}, {"$set": data})
            else:
                db.sdec_device_status.insert(data)
        except Exception as e:
            logger.error(e)
            return self.write(ret_msg(code=-1, error_message="保存设备状态出错，请稍后重试！"))

        return self.write(ret_msg())


class SetDevice(ApiBaseHandler):
    def return_result(self, device_id):
        id = "xingxing/user/" + device_id
        db = mongodb_util.db
        result = db.sdec_device_status.find_one({"_id": id})
        logger.info("device_status=%s" % result)
        if result:
            wifi = result.get("wifi", None)
            if not wifi:
                result["wifi"] = {}
        else:
            msg = [{"msg_type": "status"}]
            send_mqtt_msg(device_id, msg)
            result = {}
        return result

    async def send_request(self, device_id, type, url, value=None, upper=None, lower=None, ssid=None, password=None):
        """
        发送请求
        """
        if type in [2, 3]:
            value = self.get_parameter("value", None)
            if not value or value not in ["on", "off"]:
                return self.finish(ret_msg(code=-1, error_message="请求参数错误！"))
        else:
            if type == 4:
                error_message = "音量设置超出调控范围！"
            elif type == 1:
                error_message = "温度设置超出调控范围！"
            else:
                if not ssid:
                    return self.finish(ret_msg(code=-1, error_message="请输入要连接的wifi名称！"))

            if type != 5:
                value = int(self.get_parameter("value", 0))
                if value < lower or value > upper:
                    return self.finish(ret_msg(code=-1, error_message=error_message))

        if type == 5:
            params = dict(
                device_id=device_id,
                type=type,
                ssid=ssid,
                password=password
            )
        else:
            params = dict(
                device_id=device_id,
                type=type,
                value=value
            )

        for num in [1, 2]:
            logger.info("num=%s" % num)
            response = await self.async_request(url=url, data=params, method="POST", timeout=30)
        logger.debug("response=%s" % response)
        user_dict = json.loads(response)
        if user_dict["code"] == 0:
            counter = 0
            flag = True
            result = None
            while counter < 15 and flag:
                result = self.return_result(device_id)
                if result:
                    if type == 1 or type == 5:
                        if type == 5 or counter > 3:
                            flag = False
                    elif type == 2:
                        if result["air_dry"] == value:
                            flag = False
                    elif type == 3:
                        if result["lighting"] == value:
                            flag = False
                    elif type == 4:
                        if abs(int(result["volume"]) - value) < 7:
                            result["volume"] = value
                            flag = False

                if flag and counter == 2:
                    time.sleep(1)

                logger.info("counter=%s, device_id=%s, type=%s" % (counter, device_id, type))
                counter += 1

            if type == 4 and result:
                result["volume"] = value
                id = "xingxing/user/" + device_id
                db = mongodb_util.db
                db.sdec_device_status.update_one({"_id": id}, {"$set": {"volume": value}})
                logger.info("volume=%s" % value)

            return self.write(ret_msg(data=result))
        else:
            return self.finish(ret_msg(code=-1, error_message="系统繁忙请稍后重试！"))

    async def setup_temperature(self, device_id, url, value, ssid, password):
        """
        设置温度
        """
        type = 1
        upper_limit = 20
        lower_limit = 11
        await self.send_request(device_id, type, url, value, upper_limit, lower_limit)

    async def setup_air_dry(self, device_id, url, value, ssid, password):
        """
        设置风干
        """
        type = 2
        await self.send_request(device_id, type, url, value)

    async def setup_lighting(self, device_id, url, value, ssid, password):
        """
        设置灯光
        """
        type = 3
        await self.send_request(device_id, type, url, value)

    async def setup_volume(self, device_id, url, value, ssid, password):
        """
        设置音量
        """
        type = 4
        upper_limit = 100
        lower_limit = 0
        await self.send_request(device_id, type, url, value, upper_limit, lower_limit)

    async def setup_wifi(self, device_id, url, value, ssid, password):
        """
        设置wifi
        """
        type = 5
        await self.send_request(device_id, type, url, ssid=ssid, password=password)

    async def get(self):
        device_id = self.get_parameter("device", None)
        if not device_id:
            return self.finish(ret_msg(code=-1, error_message="请指明要控制的设备！"))

        url = f"https://{DOMAIN}/api/device_control/setup?device={device_id}"
        url = url.format(device_id=device_id)
        flag = True
        counter = 0
        response = None
        while flag and counter < 3:
            response = await self.async_request(url)
            counter += 1
            if counter >= 3:
                flag = False

        logger.debug(response)
        if response:
            result = json.loads(response)
            if result["code"] == 0:
                return self.finish(ret_msg(data=result["data"]))
            else:
                return self.finish(ret_msg(code=-1, error_message="系统繁忙请稍后重试！"))
        else:
            return self.finish(ret_msg(code=-1, error_message="系统繁忙请稍后重试！"))

    async def post(self):
        url = f"https://{DOMAIN}/api/device_control/setup"
        device_id = self.get_parameter("device", None)
        value = self.get_parameter("value", None)
        ssid = self.get_parameter("ssid", None)
        password = self.get_parameter("password", None)

        # 1=temperature=温度, 2=air-dry=风干, 3=lighting=灯光, 4=volume=音量, 5=wifi=wifi
        type = int(self.get_parameter("type", 0))
        if not type:
            self.write(ret_msg(code=-1, error_message="请指明设置类型！"))

        if not device_id:
            return self.finish(ret_msg(code=-1, error_message="请指明要控制的设备！"))

        type_list = [1, 2, 3, 4, 5]
        if type not in type_list:
            return self.finish(ret_msg(code=-1, error_message="目前只支持温度、风干、音量、灯光、wifi设置！"))

        switch = {
            1: self.setup_temperature,
            2: self.setup_air_dry,
            3: self.setup_lighting,
            4: self.setup_volume,
            5: self.setup_wifi
        }
        await switch[type](device_id, url, value, ssid, password)
